package Model.Matchmaking;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import Model.DateProfile.PersonalInfo;
import Model.DateProfile.PreferenceInfo;
import Model.Matchmaking.Match;
import Model.User;
import DBAccess.DBAccess;

public class Matchmaker {

	public static void allmatches(){
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			ps = DBAccess.con.prepareStatement("SELECT userid FROM accountdb");
			rs = ps.executeQuery();
			while(rs.next()){
				match(rs.getInt(1));
			}
			
		} catch(Exception e){
			e.printStackTrace();
		}
		DBAccess.close(ps, rs);
	}
	public static void match(int userID) {
		User user = new User(userID);
		PreferenceInfo prefs = new PreferenceInfo(userID);
		PersonalInfo info = user.getPersonalInfo();
		ArrayList<int[]> matches = new ArrayList<int[]>();
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {

			// ps =
			// DBAccess.con.prepareStatement("SELECT userID, height, weight, age, interests, religion, ethnicity FROM personaldb WHERE sex=? AND orientation=?");
			ps = DBAccess.con
					.prepareStatement("SELECT userID FROM personaldb WHERE sex=? AND orientation=? AND userID!=?");

			ps.setInt(1, info.getOrientation());
			ps.setInt(2, info.getGender());
			ps.setInt(3, userID);
			rs = ps.executeQuery();
			while (rs.next()) {
				int otherID = rs.getInt("userID");
				PreferenceInfo otherPrefs = new PreferenceInfo(otherID);
				PersonalInfo otherInfo = new PersonalInfo(otherID);
				int score = calculateScore(info, prefs, otherInfo, otherPrefs);
				int results[] = { userID, otherID, score };
				matches.add(results);
			}
			DBAccess.close(ps, rs);
			ps = DBAccess.con
					.prepareStatement("DELETE from matchmakingdb where userID=? OR otherID=?");
			ps.setInt(1, userID);
			ps.setInt(2, userID);
			ps.executeUpdate();
			ps.close();
			ps = DBAccess.con
					.prepareStatement("INSERT into matchmakingdb (userID, otherID, score) Values (?, ?, ?)");
			for (int i = 0; i < matches.size(); i++) {
				int match[] = matches.get(i);
//				System.out.println(match[0] + " " + match[1] + " " + match[2]);
				if (match[2] > 0) {
					ps.setInt(1, match[0]);
					ps.setInt(2, match[1]);
					ps.setInt(3, match[2]);
					ps.addBatch();
				}
			}
			ps.executeBatch();
			ps.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static int calculateScore(PersonalInfo info, PreferenceInfo prefs,
			PersonalInfo otherInfo, PreferenceInfo otherPrefs) {
		int score = 100;
		int herror = 0, werror = 0, aerror = 0;
		if (otherInfo.getHeight() < prefs.getHeightLower()
				|| otherInfo.getHeight() > prefs.getHeightUpper())
			herror += Math.min(
					Math.abs(otherInfo.getHeight() - prefs.getHeightLower()),
					Math.abs(otherInfo.getHeight() - prefs.getHeightUpper()));
		if (info.getHeight() < otherPrefs.getHeightLower()
				|| info.getHeight() > otherPrefs.getHeightUpper())
			herror += Math.min(
					Math.abs(info.getHeight() - otherPrefs.getHeightLower()),
					Math.abs(info.getHeight() - otherPrefs.getHeightUpper()));

		if (otherInfo.getWeight() < prefs.getWeightLower()
				|| otherInfo.getWeight() > prefs.getWeightUpper())
			werror += Math.min(
					Math.abs(otherInfo.getWeight() - prefs.getWeightLower()),
					Math.abs(otherInfo.getWeight() - prefs.getWeightUpper()));
		if (info.getWeight() < otherPrefs.getWeightLower()
				|| info.getWeight() > otherPrefs.getWeightUpper())
			werror += Math.min(
					Math.abs(info.getWeight() - otherPrefs.getWeightLower()),
					Math.abs(info.getWeight() - otherPrefs.getWeightUpper()));

		if (otherInfo.getAge() < prefs.getAgeLower()
				|| otherInfo.getAge() > prefs.getAgeUpper())
			aerror += 5 * Math.min(
					Math.abs(otherInfo.getAge() - prefs.getAgeLower()),
					Math.abs(otherInfo.getAge() - prefs.getAgeUpper()));
		if (info.getAge() < otherPrefs.getAgeLower()
				|| info.getAge() > otherPrefs.getAgeUpper())
			aerror += 5 * Math.min(
					Math.abs(info.getAge() - otherPrefs.getAgeLower()),
					Math.abs(info.getAge() - otherPrefs.getAgeUpper()));

		score -= herror + werror + aerror;
		ArrayList<String> userInterests = info.getActivityInterests();
		ArrayList<String> otherUserInterests = otherInfo.getActivityInterests();

		int intMatches = 0;
		for (int i = 0; i < userInterests.size(); i++) {
			if (otherUserInterests.contains(userInterests.get(i))) {
				intMatches++;
			}
		}

		score += 10 * intMatches;
		if (otherPrefs.getReligion() != null
				&& info.getReligion().compareTo(otherPrefs.getReligion()) != 0)
			score -= 10;
		if (otherPrefs.getEthnicity() != null
				&& info.getEthnicity().compareTo(otherPrefs.getEthnicity()) != 0)
			score -= 10;
		if (prefs.getReligion() != null
				&& otherInfo.getReligion().compareTo(prefs.getReligion()) != 0)
			score -= 10;
		if (prefs.getEthnicity() != null
				&& otherInfo.getEthnicity().compareTo(prefs.getEthnicity()) != 0)
			score -= 10;

		return score;
	}

}